package main

import (
	"fmt"
	"github.com/go-redsync/redsync/v4"
	"github.com/go-redsync/redsync/v4/redis/goredis/v9"
	goredislib "github.com/redis/go-redis/v9"
	"sync"
	"time"
)

func main() {
	// Create a pool with go-redis (or redigo) which is the pool redisync will
	// use while communicating with Redis. This can also be any pool that
	// implements the `redis.Pool` interface.
	// 创建redis 客户端
	client := goredislib.NewClient(&goredislib.Options{
		Addr:     "110.40.159.189:6379",
		Password: "Gjf5845201314gjf",
	})
	// 创建连接池对象
	pool := goredis.NewPool(client) // or, pool := redigo.NewPool(...)

	// Create an instance of redisync to be used to obtain a mutual exclusion
	// lock.
	// 创建一个用于获取互斥锁的再同步实例。
	rs := redsync.New(pool)

	mutexname := "my-global-mutex" // 给锁命个名
	var wg sync.WaitGroup          // 等待组
	var gNum = 2                   // 2个并发
	wg.Add(gNum)
	for i := 0; i < gNum; i++ {
		// 并发
		go func(_i int) {
			defer wg.Done()

			// 1.创建互斥锁对象
			mutex := rs.NewMutex(mutexname)

			// 2.获取锁
			fmt.Println("开始获取锁", _i) // 两个协程都会执行
			if err := mutex.Lock(); err != nil {
				panic(err)
			}
			fmt.Println("获取锁成功", _i) // 只有一个协程会 获取成功

			fmt.Println("执行业务逻辑处理", _i)
			time.Sleep(time.Second * 5) // 模拟执行业务逻辑

			// 3.释放锁
			fmt.Println("开始释放锁", _i) // 只有一个协程会 开始释放锁
			if ok, err := mutex.Unlock(); !ok || err != nil {
				panic("unlock failed")
			}
			fmt.Println("释放锁成功", _i) // 只有一个协程会 释放锁成功。然后下一个协程才会获取锁成功
		}(i)
	}
	wg.Wait()
}
